package it.unipd.dei.es1011.nucularc0d3.defaultproject.pref;

import it.unipd.dei.es1011.nucularc0d3.defaultproject.R;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.preference.Preference;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.SeekBar.OnSeekBarChangeListener;

/**
 * Custom SeekBar used into Settings
 * @author Spectre
 *
 */

public class SeekBarPreference extends Preference 
implements OnSeekBarChangeListener{

	private static int maximum;
	private static int minimum;
	private static int interval = 1;
	private static int textSeekBarLittleHeight = 13;
	private float oldValue;
	private int tempValue;
	private TextView monitorBox;

	public SeekBarPreference(Context context) {
		super(context);
	}

	public SeekBarPreference(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	@Override
	protected View onCreateView(ViewGroup parent){
		// retrieving maximum and minimum value for my seekBar
		Resources res = getContext().getResources();
		maximum = res.getInteger(R.integer.seekBarMax);
		minimum = res.getInteger(R.integer.seekBarMin);
		
		// layout that will contain my custom seekBar
		LinearLayout fullBox = new LinearLayout(getContext()); 
		fullBox.setOrientation(LinearLayout.VERTICAL);
		fullBox.setPadding(5, 5, 5, 5);
		
		// layout that will contain the textView
		LinearLayout context = new LinearLayout(getContext());
		context.setOrientation(LinearLayout.HORIZONTAL);
		context.setWeightSum(3);
		
		// settings parameters for the textView and seekBar
		
		// Parameters for Title textView
		LinearLayout.LayoutParams paramsForTitle = new LinearLayout.LayoutParams( 
				LinearLayout.LayoutParams.WRAP_CONTENT,
				LinearLayout.LayoutParams.WRAP_CONTENT);
		paramsForTitle.gravity = Gravity.LEFT;
		paramsForTitle.weight  = 1.0f;
		
		// Parameters for the seekBar
		LinearLayout.LayoutParams paramsForSeekBar = new LinearLayout.LayoutParams(
				LinearLayout.LayoutParams.FILL_PARENT,
				LinearLayout.LayoutParams.WRAP_CONTENT);
		paramsForSeekBar.gravity = Gravity.CENTER;

		// Parameters for MinValue textView
		LinearLayout.LayoutParams paramsForMinValue = new LinearLayout.LayoutParams( 
				LinearLayout.LayoutParams.WRAP_CONTENT,
				LinearLayout.LayoutParams.WRAP_CONTENT);
		paramsForMinValue.gravity = Gravity.LEFT;
		paramsForMinValue.weight = 1.0f;
		
		// Parameters for ActualValue textView
		LinearLayout.LayoutParams paramsForActualValue = new LinearLayout.LayoutParams(
				LinearLayout.LayoutParams.WRAP_CONTENT,
				LinearLayout.LayoutParams.WRAP_CONTENT);
		paramsForActualValue.gravity = Gravity.CENTER;
		paramsForActualValue.weight = 1.0f;

		// Parameters for MaxValue textView
		LinearLayout.LayoutParams paramsForMaxValue = new LinearLayout.LayoutParams( 
				LinearLayout.LayoutParams.WRAP_CONTENT,
				LinearLayout.LayoutParams.WRAP_CONTENT);
		paramsForMaxValue.gravity = Gravity.RIGHT;
		paramsForMaxValue.weight = 1.0f;	

		// creating and setting seekBar
		SeekBar bar = new SeekBar(getContext());
		bar.setMax(maximum);
		bar.setProgress((int)this.oldValue);
		bar.setLayoutParams(paramsForSeekBar);
		bar.setOnSeekBarChangeListener(this);
		
		//	initialization of boxes
		TextView titleView = new TextView(getContext());
		titleView.setText(getTitle());
		titleView.setTextSize(18);
		titleView.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD);
		titleView.setGravity(Gravity.LEFT);
		titleView.setLayoutParams(paramsForTitle);

		TextView minValueView = new TextView(getContext());
		minValueView.setText(minimum+"");
		minValueView.setTextSize(textSeekBarLittleHeight);
		minValueView.setTypeface(Typeface.SANS_SERIF, Typeface.NORMAL);
		minValueView.setGravity(Gravity.LEFT);
		minValueView.setLayoutParams(paramsForMinValue);
		
		monitorBox = new TextView(getContext());
		monitorBox.setTextSize(textSeekBarLittleHeight);
		monitorBox.setGravity(Gravity.CENTER);
		monitorBox.setTypeface(Typeface.MONOSPACE, Typeface.ITALIC);
		monitorBox.setLayoutParams(paramsForActualValue);
		monitorBox.setPadding(2, 5, 0, 0);
		tempValue = bar.getProgress();
		tempValue++;
		monitorBox.setText(tempValue+"");
		
		TextView maxValueView = new TextView(getContext());
		maxValueView.setText((maximum+1)+"");
		maxValueView.setTextSize(textSeekBarLittleHeight);
		maxValueView.setTypeface(Typeface.SANS_SERIF, Typeface.NORMAL);
		maxValueView.setGravity(Gravity.RIGHT);
		maxValueView.setLayoutParams(paramsForMaxValue);
		
		// adding View
		context.addView(minValueView);
		context.addView(monitorBox);
		context.addView(maxValueView);
		
		fullBox.addView(titleView);
		fullBox.addView(bar);
		fullBox.addView(context);
		fullBox.setId(android.R.id.widget_frame);

		return fullBox; 
	}

	/**
	 * Function called when the user change the value in the seekBar
	 */
	@Override
	public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {
		progress = Math.round(((float)progress)/interval)*interval;

		if(!callChangeListener(progress)){
			seekBar.setProgress((int)oldValue); 
			return; 
		}
		seekBar.setProgress(progress);
		oldValue = progress;
		monitorBox.setText((progress+1)+"");
	}

	@Override
	public void onStartTrackingTouch(SeekBar seekBar) {
	}

	/**
	 * When the user stop dragging the cursor i must save the preferences, otherwise it will be deleted.
	 */
	@Override
	public void onStopTrackingTouch(SeekBar seekBar) {
		updatePreference((int)oldValue); // update the old preferences
		notifyChanged(); // method that should be called when the data of this Preference has changed
	}

	/**
	 * I must check when i load the default value (in case there is no one)
	 */
	@Override 
	protected Object onGetDefaultValue(TypedArray ta,int index){
		int dValue = (int)ta.getInt(index,700);
		return validateValue(dValue);
	}

	@Override
	protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
		int temp = restoreValue ? getPersistedInt(700) : (Integer)defaultValue;
		if(!restoreValue)
			persistInt(temp);
		this.oldValue = temp;
	}

	/**
	 * Method used to evaluate if the value passed is good
	 * @param value to check
	 * @return the normalized value
	 */
	private int validateValue(int value){
		if(value > maximum)
			value = maximum;
		else if(value <= minimum)
			value = minimum;
		else if(value % interval != 0)
			value = Math.round(((float)value)/interval)*interval;  
		return value;  
	}

	/**
	 * Called after the user has set the new value
	 * @param newValue to be saved
	 */
	private void updatePreference(int newValue){
		SharedPreferences.Editor editor =  getEditor();
		editor.putInt("seekBarTime", newValue);
		editor.commit();
	}

}
